macheteYeti / [CCP] Inventory Services for Printavo & Online Labels

// ==UserScript==
// @name         [CCP] Inventory Services for Printavo & Online Labels
// @namespace    CCP
// @include https://www.printavo.com/*
// @include https://secure.onlinelabels.com/Account/OrderHistory.aspx
// @include https://www.onlinelabels.com/products/*
// @require http://code.jquery.com/jquery-3.4.1.min.js
// @resource customCSS https://fitaf570.com/jqui/ui-lightness.css
// @require https://code.jquery.com/ui/1.12.0/jquery-ui.min.js
// @require     https://cdnjs.cloudflare.com/ajax/libs/arrive/2.4.1/arrive.min.js
// @grant       GM_addStyle
// @grant       GM_getResourceText
// @license MIT
// @author       macheteYeti
// @description  Adds functionality to Printavo & OnlineLabels to enable stock management features.
// ==/UserScript==

var newCSS = GM_getResourceText ("customCSS");
GM_addStyle (newCSS);

GM_addStyle( `
	.inventoryTracking{position:absolute;top:0;left:0;width:27%;margin-left:3%}
	.tracked{cursor:default}
	.threeDays{left:30%}
	#inventoryDialog{width:200px;height:200px}
	.ui-dialog.ui-corner-all.ui-widget.ui-widget-content{z-index:999}
	
	#inventoryDialog input{width:150px;margin-bottom:1em}
	
	#inventoryQty.ui-state-error::placeholder{color:#fff}
	
	#genericRecord{cursor:pointer}
` );

$(document).ready(function(){

	//determine whether using Online Labels or Printavo
	var plat='ol';
	if(window.location.href.indexOf("printavo")>-1)plat='pa';
	
	//specify which machine for audit log
	user='admin';
	// user='production';
	
	//specify statuses which should trigger an inventory update
	var include=['Ready for Pickup','Delivery','Ship','In Production'];
	
	//serve different code based on which platform is in use
	switch(plat){
	
		case 'ol':
		
			if(window.location.href.indexOf('products')>-1){
			
				//if on a product page, determine if we've passed ordering parameters
				var urlParams = new URLSearchParams(window.location.search);
				if(typeof urlParams.get('qty')!=typeof undefined&&urlParams.get('qty')!=null&&urlParams.get('qty').length>0){
				
					//fill in order quantty
					$('.v-pob__custom-quantity-input').val(urlParams.get('qty'));
					setTimeout(()=>{
					
						//add to cart
						$('.v-pob__add-to-cart')[0].click();
						setTimeout(()=>{
						
							//if this is the last item to order, go to cart, otherwise close the page
							if(urlParams.get('last')==null)window.close();
							else window.location.href='https://secure.onlinelabels.com/Cart/ViewCart.aspx';
						},1500);
					},1500);
				}
			}
			else{
			
				//if we're not on a product page, we know we're on the order history page due to distinct @includes
				
				//gather up visible invoices
				var foundInvoices=[];
				$('a[href*=OrderDetails]').each(function(){ foundInvoices.push($(this).attr('href').split('?')[1]); });
				
				//check if we've tracked visible invoices
				$.ajax({type:'GET',url:'https://fitaf570.com/ccp/getStock.php',async:false,dataType:'json',data:{type:'invoices',foundInvoices:foundInvoices},fail:function(jqXHR,textStatus,errorThrown){console.log('Could not get invoices, server response: '+textStatus+': '+errorThrown);},success:function(d){
				
					var tracked='<a class="c-button c-button--secondary c-button--full u-margin-bottom--tiny inventoryTracking tracked">Inventory Tracked!</a>';
					var untracked='<a class="ss-duplicate-order c-button c-button--full u-margin-bottom--tiny inventoryTracking" style="">Track Inventory (Now)</a><a class="ss-duplicate-order c-button c-button--full u-margin-bottom--tiny inventoryTracking threeDays">Track Inventory<br>(In 3 Days)</a>';
					
					$('.p-order-box').each(function(){
					
						//for each order, based on if we find the invoice ID, put out the relevant buttons
						if($.inArray($(this).find('a[href*=OrderDetails]').attr('href').split('?')[1],d.inv)>-1)$(tracked).prependTo($(this).find('.p-order-box__totals>div').first());
						else $(untracked).prependTo($(this).find('.p-order-box__totals>div').first());
					})
				}});
				
				$(document).on('click','.inventoryTracking:not(.tracked)',function(){
				
					//when clicking an inventory button, gather the details
					var orig=$(this);
					var data={'type':'stockChange','action':'add','inv':$(this).parents('.p-order-box').find('a[href*=OrderDetails]').attr('href').split('?')[1]};
					if($(this).hasClass('threeDays'))data['when']='interval';
					else data['when']='now';
					
					//gather the products
					$(this).parents('.p-order-box').find('.u-border--top.u-large-text-align--left').find('.row.align-middle').each(function(){
					
						vals=[$(this).find('div').first().next().find('div').first().next().contents().text().trim().trimLeft()];
						$.each($(this).find('div').first().next().text().replaceAll("\n\n","\n").split("\n"),function(i,v){
						
							if(v.indexOf('Sheets')>-1)vals.push(v.trim().trimLeft().replace("Sheets","").trim().trimLeft());
						});
						data['vals']=vals;
						
						//send the data
						$.ajax({type:'GET',url:'https://fitaf570.com/ccp/getStock.php',async:false,dataType:'json',data:data});
					});
					
					//hide the recording buttons
					$(orig).parent().find('.inventoryTracking').fadeOut();
				});
			}
		break;
		case 'pa':
		
			//if we don't already have a generic inventory utilization button, add it to the top nav
			if($('#genericRecord').length==0)$('.nav.navbar-nav').prepend('<li><a class="menu-item" title="Record Supply Usage" id="genericRecord"><img width="16" height="16" class="new-item__icon" src="https://djqnomyzwkbyb.cloudfront.net/assets/app/icon-new@2x-074c3957e49b442a12334ec6132993212f3e9a0241a52251f6b9832dc17b2e62.png">Record</a></li>');
			
			//retrieve the products we will use in the autocomplete lookup
			sku=$.ajax({type:'GET',url:'https://fitaf570.com/ccp/getStock.php',async:false,dataType:'json',data:{type:'sku'},fail:function(jqXHR,textStatus,errorThrown){console.log('Could not get sku, server response: '+textStatus+': '+errorThrown);}}).responseJSON;
			
			//instantiate the popup to gather the inventory utilization
			$('body').append('<div id="inventoryDialog" style="display:none" title="Log Usage"><form autocomplete="off"><input id="inventoryQty" placeholder="Sheets used" autocomplete="off"><br><input id="inventoryLookup" placeholder="Select a Stock"><input type="hidden" id="inventoryJob"></form></div>');
			$('#inventoryDialog').dialog({autoOpen:false,width:300,position:{my:'right center',at:'right bottom',of: event}});
			//hide the popup initially
			$('#inventoryDialog').dialog('close');
			
			function openDialog(loc=1,e){
			
				/*
					loc 1 = calendar
					loc 2 = generic top nav record
					loc 3 = forced generic top nav record on invoice page load
				*/
				switch(loc){
				
					case 1:
					
						$('.jq-order-preview-modal').css('display','block');
						$('#inventoryDialog').dialog({appendTo:'.jq-order-preview-modal'})
						//set job via url in Printavo popup
						$('#inventoryJob').val($('.modal-content.modal-calendar .btn.btn-success.pull-left').attr('href').split('/')[2]);
					break;
					
					case 3:
					
						//set job via url
						$('#inventoryJob').val(window.location.href.split('/').pop());
					break;
				}
				$('#inventoryDialog').dialog("option","position",{my: "right bottom+15", of: e});
				$('#inventoryDialog').dialog('open');
				$('#inventoryQty').focus();
			}
			
			//if someone tries to look up a product before specifying a quantity, we add error styles to the quantity box. when someone starts typing in it, they are removed
			$(document).on('keydown','#inventoryQty.ui-state-error',function(){ $(this).removeClass('ui-state-error'); });
			
			$('#inventoryLookup').autocomplete({
			
				source:sku,
				width:200,
				delay:100,
				autoFocus:true,
				focus:function(){$(this).focus();},
				select:function(event,ui){
				
					//when we select a stock from the autocomplete list, check that we have specified a quantity
					if($('#inventoryQty').val().length==0){
					
						$('#inventoryQty').addClass('ui-state-error').effect('shake');
						$('#inventoryLookup').val('');
						$('#inventoryQty').focus();
						return false;
					}
					//if a quantity has been specified, gather the rest of the info
					var dat={type:'stockChange',action:'subtract',val:$('#inventoryQty').val(),id:ui.item.value,user:user,inv:$('#inventoryJob').val()};
					
					// $('#inventoryLookup').val(ui.item.label);
					
					//send the record
					$.ajax({type:'GET',url:'https://fitaf570.com/ccp/getStock.php',async:false,dataType:'json',data:dat,success:function(d){
					
						//once recorded, close the popup
						$('#inventoryDialog').dialog('close');
						$('#inventoryDialog form')[0].reset();
						$('#inventoryLookup').val('').empty();
						/* $('.jq-order-preview-modal,.modal-backdrop').css('display','none');
						$('body').removeClass('modal-open').css('padding-right','0');
						$('.jq-order-preview-modal.modal.fade.in').removeClass('in').css('padding-right','0');
						$('.modal-content.modal-calendar').empty();
						$('.HW_badge.HW_visible.HW_animated.HW_blank').removeClass('HW_blank'); */
					}});
					this.value = "";
					return false;
				}
			});
			
			if(window.location.href.indexOf('/invoices/')>-1){
			
				//if we're on an invoice page, check if we have recorded inventory usage for it
				//if not show the popup
				$.ajax({type:'GET',url:'https://fitaf570.com/ccp/getStock.php',async:false,dataType:'json',data:{type:'checkInvoice',inv:window.location.href.split('/').pop()},success:function(d){
					
					if(!d.inv)openDialog(3,$('#genericRecord'));
				}});
			}
			$(document).on('click','.dropdown-select-status__menu li',function(e){
			
				//when we change status on the calendar, if we are specifying a qualified status, show the popup
				if($.inArray($(this).text().trim().trimLeft(),include)>-1)openDialog(1,e);
			});
			
			$(document).on('click','#genericRecord',function(e){
			
				//if we click the generic record button in the top nav, show the popup
				openDialog(2,e);
			});
		break;
		default:break;
	}
});